package cn.toesbieya.jxc.service.doc;

import cn.toesbieya.jxc.annoation.Lock;
import cn.toesbieya.jxc.annoation.UserAction;
import cn.toesbieya.jxc.enumeration.DocStatusEnum;
import cn.toesbieya.jxc.mapper.NoticeMapper;
import cn.toesbieya.jxc.model.entity.*;
import cn.toesbieya.jxc.model.vo.NoticeVo;
import cn.toesbieya.jxc.model.vo.R;
import cn.toesbieya.jxc.model.vo.UserVo;
import cn.toesbieya.jxc.model.vo.result.PageResult;
import cn.toesbieya.jxc.model.vo.search.NoticeSearch;
import cn.toesbieya.jxc.model.vo.update.DocStatusUpdate;
import cn.toesbieya.jxc.service.RecService;
import cn.toesbieya.jxc.util.DocUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class NoticeService {

    @Resource
    private NoticeMapper mainMapper;

    @Resource
    private RecService recService;

    //组装子表、附件列表的数据
    public NoticeVo getById(String id) {
        Notice main = mainMapper.selectById(id);

        if (main == null) return null;

        NoticeVo vo = new NoticeVo(main);

        vo.setImageList(recService.getAttachmentByPid(id));

        return vo;
    }

    //根据主表ID获取子表
    public List<Notice> getSubById(String id) {
        ArrayList<Notice> list = new ArrayList<>();
        list.add(mainMapper.selectById(id));
        return list;
    }

    public PageResult<Notice> search(NoticeSearch vo) {
        PageHelper.startPage(vo.getPage(), vo.getPageSize());
        String status = vo.getStatus();
        String name = vo.getName();
        Integer pid = vo.getPid();
        Integer pname = vo.getPname();
        LocalDateTime ctimeStart = vo.getCtimeStart();
        LocalDateTime ctimeEnd = vo.getCtimeEnd();
        return new PageResult<>(mainMapper.selectList(new QueryWrapper<Notice>().lambda()
                .inSql(!StringUtils.isEmpty(status), Notice::getStatus, status)
                .like(name!=null,Notice::getName,name)
                .eq(pid!=null,Notice::getPid,pid)
                .like(pname!=null,Notice::getPname,pname)
                .ge(ctimeStart != null, Notice::getCtime, ctimeStart)
                .le(ctimeEnd != null, Notice::getCtime, ctimeEnd)
        ));
    }


    @UserAction("'添加发布信息'")
    @Transactional(rollbackFor = Exception.class)
    public R add(NoticeVo doc) {
        return addMain(doc);
    }

    @UserAction("'修改发布信息'+#doc.id")
    @Lock("#doc.id")
    @Transactional(rollbackFor = Exception.class)
    public R update(NoticeVo doc) {
        return updateMain(doc);
    }

    @UserAction("'提交发布信息'+#doc.id")
    @Lock("#doc.id")
    @Transactional(rollbackFor = Exception.class)
    public R commit(NoticeVo doc) {
        boolean isFirstCreate = com.baomidou.mybatisplus.core.toolkit.StringUtils.isEmpty(doc.getId());
        R result = isFirstCreate ? addMain(doc) : updateMain(doc);

        if (result.isSuccess()) {
            result.setMsg("提交成功");
        } else result.setMsg("提交失败，" + result.getMsg());

        return result;
    }

    @UserAction("'通过发布'+#vo.id")
    @Lock("#vo.id")
    @Transactional(rollbackFor = Exception.class)
    public R pass(DocStatusUpdate vo, UserVo user) {
        String id = vo.getId();
        LocalDateTime now = LocalDateTime.now();
        if (0 == mainMapper.update(
                null,
                Wrappers.lambdaUpdate(Notice.class)
                        .set(Notice::getStatus, DocStatusEnum.VERIFIED.getCode())
                        .eq(Notice::getId, id)
                        .set(Notice::getVname, user.getNickName())
                        .set(Notice::getVtime, now)
                        .eq(Notice::getStatus, DocStatusEnum.WAIT_VERIFY.getCode())
        )) {
            return R.fail("通过失败，请刷新重试");
        }

        return R.success("通过成功");
    }


    @UserAction("'删除发布信息'+#id")
    @Lock("#id")
    @Transactional(rollbackFor = Exception.class)
    public R del(String id) {
        if (mainMapper.deleteById(id) < 1) {
            return R.fail("删除失败");
        }
        recService.delAttachmentByPid(id);

        return R.success("删除成功");
    }


    private R addMain(NoticeVo doc) {
        String id = DocUtil.getDocId("NOTICE");

        if (org.springframework.util.StringUtils.isEmpty(id)) {
            return R.fail("获取公告号失败");
        }
        doc.setId(id);
        //插入主表和子表
        mainMapper.insert(doc);


        //插入附件
        List<RecAttachment> uploadImageList = doc.getUploadImageList();
        Long time = System.currentTimeMillis();
        for (RecAttachment attachment : uploadImageList) {
            attachment.setPid(id);
            attachment.setTime(time);
        }
        recService.handleAttachment(uploadImageList, null);

        return R.success("添加成功", id);
    }


    private R updateMain(NoticeVo doc) {
        String docId = doc.getId();
        //更新主表
        mainMapper.updateById(doc);
        //附件增删
        List<RecAttachment> uploadImageList = doc.getUploadImageList();
        Long time = System.currentTimeMillis();
        for (RecAttachment attachment : uploadImageList) {
            attachment.setPid(docId);
            attachment.setTime(time);
        }
        recService.handleAttachment(uploadImageList, doc.getDeleteImageList());

        return R.success("修改成功");
    }

}
